--物品能合成的表
local item_father_data = {}
--物品的合成表
local item_compound_data = {}
--物品合成str
local item_compound_str = {}
--需要和成书的物品
local item_book = {}

local item_data_list = ac.lni('item')

local function init()
    for name, data in pairs(item_data_list) do
        --物品合成数据处理
        if data.compound then
            local function cal(com)
                for k, item_com in pairs(com) do
                    if type(item_com) == 'table' then
                        cal(item_com)
                    else
                        local list = item_father_data[item_com]
                        if not list then
                            list = {}
                            item_father_data[item_com] = list
                            list.map = {}
                        end
                        if list.map[name] == nil then
                            list.map[name] = true
                            table.insert(list, name)
                        end

                        if not item_compound_data[name] then
                            item_compound_data[name] = {}
                        end
                        table.insert(item_compound_data[name], item_com)
                    end
                end
            end
            cal(data.compound)
            --list = nil
        end
    end

    --物品合成说明处理
    for bas, data in pairs(item_father_data) do
        local s = {}
        for _, fa in ipairs(data) do
            for k, data2 in ipairs(item_compound_data[fa]) do
                s[#s + 1] = data2
                s[#s + 1] = ' + '
            end
            table.remove(s, #s)
            s[#s + 1] = ' = ' .. fa
            s[#s + 1] = '\n'
        end
        table.remove(s, #s)
        local str = table.concat(s)
        item_compound_str[bas] = str


        table.sort(data, function(a, b)
            return #item_compound_data[a] < #item_compound_data[b]
        end)
    end
end



local function get_item_father_data(name)
    return item_father_data[name]
end

local function get_item_compound_data(name)
    local data = ac.lni('item', name)
    if data == nil then
        return
    end
    return data.compound
end

local function get_item_compound_str(name)
    return item_compound_str[name] or ''
end

--获取合成信息 参数 单位，其中一个物品
--返回1 可合成的物品名字 | nil
--返回2 材料列表 {item, ...}
local function get_compound_item_info(unit, item)
    local player = unit:get_owner()

    --取该物品可以合成的所有公式表
    local father = get_item_father_data(item:get_id())

    if not father then
        return false, {}
    end

    local count_map = {}

    local items = unit:get_items()

    local has = false
    for index, it in ipairs(items) do
        if it == item then
            has = true
        end
    end
    if has == false then
        table.insert(items, item)
    end

    for index, it in ipairs(items) do
        local name = it:get_id()
        count_map[name] = (count_map[name] or 0) + 1
    end

    local function get_item(name, map)
        for i, it in ipairs(items) do
            if map[it] == nil and it:get_id() == name then
                map[it] = true
                return it
            end
        end
    end

    --检查合成公式 参数 材料 目标
    local function check_compound(compound)
        local can = false

        local tbl = {}
        for k, v in pairs(count_map) do
            tbl[k] = v
        end

        local has_count = 0
        local map = {}
        local list = {}
        for _, name in ipairs(compound) do
            if tbl[name] == nil then
                return false, list
            end

            if tbl[name] <= 0 then
                return false, list
            end
            local it = get_item(name, map)
            if it then
                tbl[name] = tbl[name] - 1

                has_count = has_count + 1
                table.insert(list, it)
            end
        end

        if has_count == #compound and has_count > 0 then
            return true, list
        end

        return false, list
    end

    for index, target in ipairs(father) do
        local compoud = get_item_compound_data(target)
        if compoud then
            if type(compoud[1]) == 'table' then
                for i, tbl in ipairs(compoud) do
                    local can, list = check_compound(tbl)
                    if can then
                        return target, list
                    end
                end
            else
                local can, list = check_compound(compoud)
                if can then
                    return target, list
                end
            end
        end
    end
end

local function item_compound(unit, item)
    local name, list = get_compound_item_info(unit, item)
    if not name then
        return false
    end
    local data = ac.item[name]
    if data and data.on_compound and data:on_compound(unit) == false then
        return false
    end
    for i, it in ipairs(list) do
        it:remove()
    end
    local item = unit:add_item(name)
    local effect = unit:add_effect('Abilities\\Spells\\NightElf\\ManaBurn\\ManaBurnTarget.mdl', 'origin')
    unit:wait(300, function()
        effect:remove()
    end)
    return true
end

ac.game:on '单位-检查物品合成' (function(_, unit, item)
    local name, list = get_compound_item_info(unit, item)
    if not name then 
        return false 
    end 
    return true
end)

ac.game:on '单位-合成物品' (function(_, unit, item)
    return item_compound(unit, item)
end)

init()
